Skip to content

Conversation

peterfriese
Copy link
Contributor

@peterfriese peterfriese commented Sep 22, 2025

This PR introduces a new configUpdates property to RemoteConfig, providing an AsyncThrowingStream for consuming real-time config updates. This offers a modern, Swift Concurrency-native alternative to the existing closure-based listener, making it easier to integrate real-time updates into async/await workflows.

Motivation

The existing addOnConfigUpdateListener uses a closure-based callback, which can be cumbersome in modern Swift applications that have adopted Swift Concurrency. By providing an AsyncThrowingStream, we offer a more ergonomic and idiomatic way for developers to receive real-time updates, simplifying their code and improving readability.

Implementation Details

  • FirebaseRemoteConfig/Swift/RemoteConfig+Async.swift: A new file containing an extension on RemoteConfig.

    • It adds a public configUpdates property that returns an AsyncThrowingStream<RemoteConfigUpdate, Error>.
    • The stream's implementation wraps the existing addOnConfigUpdateListener.
    • The listener's lifecycle is automatically managed: it is added when iteration begins and removed when the stream is terminated (e.g., through cancellation).
  • FirebaseRemoteConfig/Tests/Swift/SwiftAPI/AsyncStreamTests.swift: A new test suite for the async stream functionality.

    • Includes mock objects to simulate the real-time service and listener registration.
    • Contains tests for various scenarios, including successful updates, error handling, stream cancellation, and handling of multiple updates.

Example usage

Developers can now listen for real-time updates using a simple for try await loop:

func listenForRealtimeUpdates() {
  Task {
    do {
      for try await configUpdate in remoteConfig.configUpdates {
        print("Updated keys: \(configUpdate.updatedKeys)")

        // Activate the new config to make it available
        let status = try await remoteConfig.activate()
        print("Config activated with status: \(status)")
      }
    } catch {
      print("Error listening for remote config updates: \(error)")
    }
  }
}

This change is purely additive and does not affect any existing APIs.

@peterfriese peterfriese self-assigned this Sep 22, 2025
@peterfriese peterfriese linked an issue Sep 22, 2025 that may be closed by this pull request
@peterfriese peterfriese marked this pull request as ready for review September 22, 2025 21:52
Copy link
Member

@paulb777 paulb777 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - thanks @peterfriese !

Leaving approval to @ncooke3 or the RC team

@ncooke3 ncooke3 closed this Oct 2, 2025
@ncooke3
Copy link
Member

ncooke3 commented Oct 2, 2025

Closing and re-opening to trigger all CI checks again.

@ncooke3 ncooke3 reopened this Oct 2, 2025
Copy link
Member

@ncooke3 ncooke3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some suggestions to fix current CI errors. Also suggesting to change doc comment and changelog to prefer sequence over stream (impl. detail).

@ncooke3
Copy link
Member

ncooke3 commented Oct 2, 2025

Down to one linting failure (unit test flake?). Rerunning:

      - NOTE  | [iOS] xcodebuild:  2025-10-02 22:29:13.149516+0000 AppHost-FirebaseRemoteConfig-Unit-Tests[92144:368595] [[FirebaseRemoteConfig]] 12.4.0 - [FirebaseRemoteConfig][I-RCN000073] Failed to get installations token. Error : Error Domain=com.firebase.installations Code=0 "The server responded with an error: 

@ncooke3
Copy link
Member

ncooke3 commented Oct 3, 2025

Down to one linting failure (unit test flake?). Rerunning:

      - NOTE  | [iOS] xcodebuild:  2025-10-02 22:29:13.149516+0000 AppHost-FirebaseRemoteConfig-Unit-Tests[92144:368595] [[FirebaseRemoteConfig]] 12.4.0 - [FirebaseRemoteConfig][I-RCN000073] Failed to get installations token. Error : Error Domain=com.firebase.installations Code=0 "The server responded with an error: 

Perhaps not a flake. Going to see how to surface which test this is coming from.

@ncooke3
Copy link
Member

ncooke3 commented Oct 3, 2025

I haven't been able to reproduce:

    Testing started
 -> FirebaseRemoteConfig (12.4.0)
    - NOTE  | xcodebuild:  note: Using codesigning identity override: -
    - NOTE  | xcodebuild:  note: Building targets in dependency order
    - NOTE  | [iOS] xcodebuild:  note: Target dependency graph (18 targets)
    - NOTE  | xcodebuild:  note: Metadata extraction skipped. No AppIntents.framework dependency found. (in target 'FirebaseSharedSwift' from project 'Pods')
    - NOTE  | xcodebuild:  note: Metadata extraction skipped. No AppIntents.framework dependency found. (in target 'FirebaseRemoteConfigInterop' from project 'Pods')
    - NOTE  | xcodebuild:  note: Metadata extraction skipped. No AppIntents.framework dependency found. (in target 'FirebaseCoreInternal' from project 'Pods')
    - NOTE  | xcodebuild:  note: Metadata extraction skipped. No AppIntents.framework dependency found. (in target 'FirebaseRemoteConfig' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Signing static framework with --generate-pre-encrypt-hashes (in target 'Pods-App' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Metadata extraction skipped. No AppIntents.framework dependency found. (in target 'App' from project 'App')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'App' from project 'App')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'Pods-App' from project 'Pods')
    - NOTE  | xcodebuild:  Pods.xcodeproj: warning: The iOS Simulator deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 9.0, but the range of supported deployment target versions is 12.0 to 18.2.99. (in target 'PromisesObjC' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'PromisesObjC' from project 'Pods')
    - NOTE  | xcodebuild:  Pods.xcodeproj: warning: The iOS Simulator deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 9.0, but the range of supported deployment target versions is 12.0 to 18.2.99. (in target 'PromisesObjC-FBLPromises_Privacy' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'PromisesObjC-FBLPromises_Privacy' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'GoogleUtilities-GoogleUtilities_Privacy' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'GoogleUtilities' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'FirebaseSharedSwift' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'FirebaseRemoteConfigInterop' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'FirebaseRemoteConfig-FirebaseRemoteConfig_Privacy' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'FirebaseRemoteConfig' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'FirebaseInstallations-FirebaseInstallations_Privacy' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'FirebaseInstallations' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'FirebaseCoreInternal-FirebaseCoreInternal_Privacy' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'FirebaseCoreInternal' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'FirebaseCore-FirebaseCore_Privacy' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'FirebaseCore' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'FirebaseABTesting-FirebaseABTesting_Privacy' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Disabling previews because SWIFT_VERSION is set and SWIFT_OPTIMIZATION_LEVEL=-O, expected -Onone (in target 'FirebaseABTesting' from project 'Pods')
    - NOTE  | xcodebuild:  note: Target dependency graph (19 targets)
    - NOTE  | xcodebuild:  note: Using stub executor library without Swift entry point. (in target 'AppHost-FirebaseRemoteConfig-Unit-Tests' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Metadata extraction skipped. No AppIntents.framework dependency found. (in target 'FirebaseRemoteConfig-Unit-unit' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  The server responded with an error: 
    - NOTE  | [iOS] xcodebuild:  2025-10-03 10:15:06.050224-0400 AppHost-FirebaseRemoteConfig-Unit-Tests[52071:8570339] [[FirebaseRemoteConfig]] 12.4.0 - [FirebaseRemoteConfig][I-RCN000073] Failed to get installations token. Error : Error Domain=com.firebase.installations Code=0 "The server responded with an error: 
    - NOTE  | [iOS] xcodebuild:  " UserInfo={NSLocalizedFailureReason=The server responded with an error: 
    - NOTE  | [iOS] xcodebuild:  note: Metadata extraction skipped. No AppIntents.framework dependency found. (in target 'FirebaseRemoteConfig-Unit-swift-api-tests' from project 'Pods')
    - NOTE  | [iOS] xcodebuild:  note: Metadata extraction skipped. No AppIntents.framework dependency found. (in target 'FirebaseRemoteConfig-Unit-fake-console-tests' from project 'Pods')

FirebaseRemoteConfig passed validation.
nickcooke@nickcooke-mac2 firebase (peterfriese/asyncsequences/remoteconfig) % xcode-select -p
/Applications/Xcode_16.2.app/Contents/Developer

@ncooke3
Copy link
Member

ncooke3 commented Oct 3, 2025

Should be OK to ignore, I verified that the new test suite you added is running and passing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement AsyncStream support for Remote Config
3 participants